# 加载基本内容
from libs import ssd1306

from machine import Pin, SoftI2C, RTC
import network
import esp32

from time import sleep
import os

# 判断是否初始化过
SCREEN_IS_INIT=0
BUTTON_IS_INIT=0
NETWORK_IS_INIT=0
def init_SCREEN(): # 初始化屏幕
    global SCREEN_IS_INIT
    if SCREEN_IS_INIT==0:
        global i2c,oled_width,oled_height,oled
        i2c = SoftI2C(scl=Pin(22), sda=Pin(21)) # 软件i2c
        oled_width = 128
        oled_height = 64
        oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)
        oled.font_load("/font/system-12.fon") # 定制固件，加载字体
        SCREEN_IS_INIT=1
    oled.fill(0) # 无论是否初始化都清空屏幕
    oled.show()
    return oled
def init_BUTTON(): # 初始化按钮
    global BUTTON_IS_INIT
    if BUTTON_IS_INIT==0:
        global button_UP,button_DOWN,button_LEFT,button_RIGHT,button_A,button_B
        button_UP=Pin(25,Pin.IN,pull=Pin.PULL_UP)
        button_DOWN=Pin(26,Pin.IN,pull=Pin.PULL_UP)
        button_LEFT=Pin(27,Pin.IN,pull=Pin.PULL_UP)
        button_RIGHT=Pin(32,Pin.IN,pull=Pin.PULL_UP)
        button_A=Pin(33,Pin.IN,pull=Pin.PULL_UP)
        button_B=Pin(16,Pin.IN,pull=Pin.PULL_UP)
        BUTTON_IS_INIT=1
        
        # 禁用按钮及按钮状态，为远控准备
        global BUTTON_disible_btn,BUTTON_btn_up,BUTTON_btn_down,BUTTON_btn_left,BUTTON_btn_right,BUTTON_btn_a,BUTTON_btn_b
        BUTTON_disible_btn=False
        BUTTON_btn_up=False
        BUTTON_btn_down=False
        BUTTON_btn_left=False
        BUTTON_btn_right=False
        BUTTON_btn_a=False
        BUTTON_btn_b=False
def init_NETWORK(): # 初始化网络
    global NETWORK_IS_INIT
    if NETWORK_IS_INIT==0:
        global wifi
        wifi = network.WLAN(network.STA_IF)
        wifi.active(True)
        NETWORK_IS_INIT=1
        
class button: # 按钮功能封装
    def get(i): # 获取
        global BUTTON_disible_btn
        if BUTTON_disible_btn: # 检查按钮禁用
            global BUTTON_btn_up,BUTTON_btn_down,BUTTON_btn_left,BUTTON_btn_right,BUTTON_btn_a,BUTTON_btn_b
            if(i=="UP"):
                return BUTTON_btn_up
            if(i=="DOWN"):
                return BUTTON_btn_down
            if(i=="LEFT"):
                return BUTTON_btn_left
            if(i=="RIGHT"):
                return BUTTON_btn_right
            if(i=="A"):
                return BUTTON_btn_a
            if(i=="B"):
                return BUTTON_btn_b
        else:
            if(i=="UP"):
                return not bool(button_UP.value())
            if(i=="DOWN"):
                return not bool(button_DOWN.value())
            if(i=="LEFT"):
                return not bool(button_LEFT.value())
            if(i=="RIGHT"):
                return not bool(button_RIGHT.value())
            if(i=="A"):
                return not bool(button_A.value())
            if(i=="B"):
                return not bool(button_B.value())
        
class screen: # 屏幕封装
    def load_csf(file): # 加载简单字体
        with open(file) as file:
            n=file.readlines()
        return n
    def show_csf(csf_list,ix,iy,s,fid): # 显示简单字体（非常慢）
        ii=0
        for y in range(int(csf_list[1])):
            for x in range(int(csf_list[0])):
                oled.fill_rect(ix+x*s,iy+y*s,s,s,int(csf_list[fid+2][y*int(csf_list[0])+x]))
                
    def WEIGHTS_btn_show(x,y,w,h,bg,fg,text,event,eid=2,is_sel=0): # 绘制按钮（未使用）
        if(bg>fg): # 传统northstar转micronorth
            bg=0
            fg=1
        else:
            bg=1
            fg=0
        oled.fill_rect(x+5, y, w-10, h, bg)
        oled.fill_rect(x, y+5, w, h-10, bg)
        oled.draw_circle(x+5,y+5,5,bg,1)
        oled.draw_circle(x+w-6,y+5,5,bg,1)
        oled.draw_circle(x+5,y+h-6,5,bg,1)
        oled.draw_circle(x+w-6,y+h-6,5,bg,1)
        if is_sel==0: # 是否选中
            oled.text(text,x+5,y+(w//2)-18,fg)
        else:
            oled.fill_rect(x+7, y+2, w-14, h-4, fg)
            oled.fill_rect(x+2, y+7, w-4, h-14, fg)
            oled.draw_circle(x+7,y+7,5,fg,1)
            oled.draw_circle(x+w-8,y+7,5,fg,1)
            oled.draw_circle(x+7,y+h-8,5,fg,1)
            oled.draw_circle(x+w-8,y+h-8,5,fg,1)
            oled.text(text,x+5,y+(w//2)-18,bg)
    def show_list(items): # 显示列表
        thisItem=0 # 当前选项
        pItem=items # 选项
        roots=[] # 路径下标列表
        rootname=[] # 路径名称列表
        def ref(items,thisitem,root): # 刷新
            roottext=">" # 根目录符号
            for i in root:
                roottext= roottext + i + '>' # 目录分隔符
            n=16 # 当前选项的相对位置
            f=0 # 目录列表向上的偏移（像素）
            if len(items)>3 and thisitem>0:
                f=(thisitem-1)*16
            oled.fill_rect(0,0,128,64,0)
            for i in items:
                if str(type(i)) == "<class 'str'>": # 判断类型是否是选项
                    oled.text(i,4,n-f,1) # 类型是选项
                else: # 类型是子目录
                    oled.text(i[0],4,n-f,1)
                    oled.text('>',116,n-f,1)
                if ((n/16)-1) == thisitem: oled.fill_rect(0,n+2-f,2,8,1)
                n+=16
            oled.fill_rect(0,0,128,14,1)
            oled.text(roottext,4,1,0)
            oled.show()
        ref(pItem,thisItem,roots) # 刷新
        while 1:
            if button.get('UP'): # 上键操作
                thisItem-=1
                if thisItem<0: # 循环
                    thisItem=len(pItem)-1
                while button.get('UP'): pass # 直到松开
                ref(pItem,thisItem,rootname)
            if button.get('DOWN'):
                thisItem+=1
                if thisItem>=len(pItem): # 循环
                    thisItem=0
                while button.get('DOWN'): pass # 直到松开
                ref(pItem,thisItem,rootname)
            if button.get('A'):
                while button.get('A'): pass # 直到松开
                
                if str(type(pItem[thisItem])) == "<class 'str'>": # 是选项就退出
                    break
                rootname.append(pItem[thisItem][0]) # 添加选项到路径
                roots.append(thisItem) # 添加选项到路径
                pItem=pItem[thisItem][1] # 当前选项
                thisItem=0 # 重置当前选项
                ref(pItem,thisItem,rootname)
            if button.get('B'):
                while button.get('B'): pass # 直到松开
                if len(roots)!=0: # 返回上级
                    del roots[-1]
                    del rootname[-1]
                    pItem=items;
                    for i in roots: # 目录回溯
                        pitem=pitem[i][1]
                    ref(pItem,thisItem,rootname)
                
        roots.append(thisItem) # 最后的选项
        return roots
    
    def input_text(info_text): # 文本输入
        with open("system/cn.kbw") as file: # 导入字典文件（只导入索引）
            cn_words=eval(file.readline()) # 索引内容
            cnwstart=file.tell() # 查找文本的起始
        is_sel=1
        keyboard_text={ # 键盘配置
                0:[ # 数字
                    [" 1 "," 2 "," 3 ","NUM"],
                    [" 4 "," 5 "," 6 "," 0 "],
                    [" 7 "," 8 "," 9 ","..."],
                ],
                1:[ # 英文小写
                    ["   ","abc","def","ENG"],
                    ["ghi","jkl","mno",".  "],
                    ["pqrs","tuv","wxyz","cap"],
                ],
                2:[ # 中文
                    ["选字","abc","def","CHN"],
                    ["ghi","jkl","mno","， "],
                    ["pqrs","tuv","wxyz","。 "],
                ],
                4:[ # 符号
                    [".,?",":;!","\"'@","SGN"],
                    ["{}/","[]\\","+=-","|#$"],
                    ["<>%","-^*","()~","《》"],
                ],
                5:[ # 英文大写
                    ["   ","ABC","DEF","ENG"],
                    ["GHI","JKL","MNO","_  "],
                    ["PQRS","TUV","WXYZ","CAP"],
                ]
        }
        china_sel=0 # 中文选项的选择
        cn_input="" # 中文正在输入
        def show_kb(info,text,sel_x,sel_y,mode): # 显示键盘
            nonlocal china_sel
            oled.fill_rect(0,0,128,64,0)
            oled.fill_rect(0,0,128-16-4,12,1)
            oled.text(info,0,0,0)
            oled.text(text,0,12)
            oled.rect(0,24,128-16,1,1)
            oled.fill_rect(128-16,0,16,64,1)
            oled.fill_rect(128-16+1,1,15,63,0)
            oled.rect(sel_x*28,sel_y*13+25,28,13,1)
            for i in range(3): # 显示键盘图案
                for j in range(4):
                    oled.text(keyboard_text[mode][i][j],j*28+5,i*13+25+1,1)
            if mode==2: # 中文特殊关照
                oled.fill_rect(128-16+2,5,2,8,1)
                j=2
                with open("system/cn.kbw") as f: # 找字
                    if cn_input in cn_words:
                        f.seek(cnwstart+cn_words[cn_input]+3*china_sel)
                        for i in range(china_sel,china_sel+5):
                            cnword=f.read(1)
                            if cnword=="。": # 读到分隔符
                                break;
                            oled.text(cnword,128-16+4,j,1)
                            j+=12
            oled.show()
        text="" # 当前文本
        cursur=0
        cur_x=0 # 光标x
        cur_y=0 # 光标y
        show_mode=0 # 当前模式
        n=0
        show_kb(info_text,text,cur_x,cur_y,show_mode)
        while 1:
            if button.get('UP'):
                cur_y-=1
                if cur_y<0: # 循环
                    cur_y=3-1
                while button.get('UP'): pass
                if show_mode!=2:
                    show_kb(info_text,text,cur_x,cur_y,show_mode) # 显示中文拼音
                else:
                    show_kb(">"+cn_input,text,cur_x,cur_y,show_mode)
            if button.get('DOWN'):
                cur_y+=1
                if cur_y>=3: # 循环
                    cur_y=0
                while button.get('DOWN'): pass
                if show_mode!=2:
                    show_kb(info_text,text,cur_x,cur_y,show_mode) # 显示中文拼音
                else:
                    show_kb(">"+cn_input,text,cur_x,cur_y,show_mode)
            if button.get('LEFT'):
                cur_x-=1
                if cur_x<0:
                    cur_x=4-1
                while button.get('LEFT'): pass
                if show_mode!=2:
                    show_kb(info_text,text,cur_x,cur_y,show_mode)
                else:
                    show_kb(">"+cn_input,text,cur_x,cur_y,show_mode)
            if button.get('RIGHT'):
                cur_x+=1
                if cur_x>=4:
                    cur_x=0
                while button.get('RIGHT'): pass
                if show_mode!=2:
                    show_kb(info_text,text,cur_x,cur_y,show_mode)
                else:
                    show_kb(">"+cn_input,text,cur_x,cur_y,show_mode)
            if button.get('A'): # 按键A按下，划重点
                while button.get('A'): pass
                if cur_x==3 and cur_y==0: # 切换模式
                    if show_mode>=3: # 对于两个特殊模式（从其他模式进入）处理
                        if show_mode==4:
                            show_mode=0
                        if show_mode==5:
                            show_mode=1
                    else:
                        show_mode+=1
                        if show_mode>=3: # 循环，不显示特殊模式
                            show_mode=0
                else:
                    if show_mode==0: # 数字模式
                        if cur_x==3 and cur_y==2: # 进入特殊模式-标点符号
                            show_mode=4
                        else: # 原样输入
                            text=text+keyboard_text[show_mode][cur_y][cur_x][1]
                    if show_mode==1 or show_mode==5: # 英文大小写
                        if cur_x==3 and cur_y==2: # 大小写切换
                            show_mode=5
                        else:
                            n=0 # 选字
                            show_kb(info_text,text+"["+keyboard_text[show_mode][cur_y][cur_x][n]+"]",cur_x,cur_y,show_mode)
                            while not button.get('B'): # 确定
                                if button.get('A'): # 输入
                                    n+=1
                                    if n>=len(keyboard_text[show_mode][cur_y][cur_x]): # 循环
                                        n=0
                                    show_kb(info_text,text+"["+keyboard_text[show_mode][cur_y][cur_x][n]+"]",cur_x,cur_y,show_mode) # 临时显示当前的
                                    while button.get('A'): pass
                            while button.get('B'): pass
                            text=text+keyboard_text[show_mode][cur_y][cur_x][n]
                    if show_mode==4: # 特殊符号
                        n=0
                        show_kb(info_text,text+"["+keyboard_text[show_mode][cur_y][cur_x][n]+"]",cur_x,cur_y,show_mode)
                        while not button.get('B'):
                            if button.get('A'):
                                n+=1
                                if n>=len(keyboard_text[show_mode][cur_y][cur_x]):
                                    n=0
                                show_kb(info_text,text+"["+keyboard_text[show_mode][cur_y][cur_x][n]+"]",cur_x,cur_y,show_mode)
                                while button.get('A'): pass
                        while button.get('B'): pass
                        text=text+keyboard_text[show_mode][cur_y][cur_x][n]
                    if show_mode==2: # 中文
                        n=0
                        show_kb(">"+cn_input+"["+keyboard_text[show_mode][cur_y][cur_x][n]+"]",text,cur_x,cur_y,show_mode)
                        
                        if cur_x==0 and cur_y==0: # 进入选字
                            with open("system/cn.kbw") as f:
                                if cn_input in cn_words:
                                    f.seek(cnwstart+cn_words[cn_input]) # 找字
                                    china_sel=0 # 第n个字
                                    show_kb("#"+cn_input,text,cur_x,cur_y,show_mode)
                                    while not button.get('A'):
                                        if button.get('UP'):
                                            if china_sel>0:
                                                china_sel-=1
                                                show_kb("#"+cn_input,text,cur_x,cur_y,show_mode)
                                            while button.get('UP'): pass
                                        if button.get('DOWN'):
                                            f.seek(cnwstart+cn_words[cn_input]+3*china_sel+3)
                                            if f.read(1)!="。":
                                                china_sel+=1
                                                show_kb("#"+cn_input,text,cur_x,cur_y,show_mode)
                                            while button.get('DOWN'): pass
                                    while button.get('A'): pass
                                    f.seek(cnwstart+cn_words[cn_input]+3*china_sel)
                                    text=text+f.read(1)
                                    
                                        
                        else: # 打拼音
                            while not button.get('B'):
                                if button.get('A'):
                                    n+=1
                                    if n>=len(keyboard_text[show_mode][cur_y][cur_x]):
                                        n=0
                                    show_kb(">"+cn_input+"["+keyboard_text[show_mode][cur_y][cur_x][n]+"]",text,cur_x,cur_y,show_mode)
                                    while button.get('A'): pass
                            while button.get('B'): pass
                            cn_input=cn_input+keyboard_text[show_mode][cur_y][cur_x][n]
                            show_kb(cn_input,text,cur_x,cur_y,show_mode)
                if show_mode!=2: # 特殊关照中文
                    show_kb(info_text,text,cur_x,cur_y,show_mode)
                else:
                    show_kb(">"+cn_input,text,cur_x,cur_y,show_mode)
            if button.get('B'): # 删除/确定
                for _ in range(100): # 长按检查
                    if not button.get('B'): # 删除
                        if show_mode!=2: # 中文
                            if len(text)>0:
                                text=text[:-1]
                            show_kb(info_text,text,cur_x,cur_y,show_mode)
                        else: # 其他
                            if len(cn_input)>0:
                                cn_input=cn_input[:-1]
                            elif len(text)>0:
                                text=text[:-1]
                            show_kb(">"+cn_input,text,cur_x,cur_y,show_mode)
                        break
                    sleep(0.01)
                else:
                    break # 退出
        return text



    
class networks: # 网络封装
    def connect_menu(): # 连接菜单
        global wifi
        init_SCREEN()
        init_BUTTON()
        f=wifi.scan() # 扫描wifi
        if len(f)==0: # 没有wifi（笑）
            return 1 # 该报错就报错（列表不支持空显示）
        wifishowlist=[]
        islock='||' # 是否开放
        for i in f:
            if i[4]==3 or i[4]==4: # 安全级别
                islock='[]' # 安全
            else:
                islock='||' # 开放
            if (i[3]*-1)<45: # 信号
                wifishowlist.append(islock[0]+'==='+islock[1]+i[0].decode('utf-8'))
            elif (i[3]*-1)<70:
                wifishowlist.append(islock[0]+'== '+islock[1]+i[0].decode('utf-8'))
            else:
                wifishowlist.append(islock[0]+'=  '+islock[1]+i[0].decode('utf-8'))
        n=screen.show_list(wifishowlist)[0] # 显示列表
        if f[n][4]==3 or f[n][4]==4: # 安全连接
            with open('/config/wifi.cfg',"a") as file:pass # 创建文件
            with open('/config/wifi.cfg',"r") as file: # 读配置
                nl=file.readlines()
            if len(nl)>=2 and nl[0][:-1]==(f[n][0].decode('utf-8')): # utf8避免锟斤拷
                wifi.connect(f[n][0].decode('utf-8'),str(nl[1])) # 尝试连接
                sleep(5)
                print("use config wifi password") # 使用密码
                if wifi.isconnected(): # 是否链接
                    return wifi.isconnected()
            pwd=screen.input_text("passwd:") # 密码不对询问密码
            wifi.connect(f[n][0].decode('utf-8'),str(pwd))
            sleep(5)
            return wifi.isconnected()
        else: # 开放
            wifi.connect(f[n][0].decode('utf-8'))
            sleep(5)
            return wifi.isconnected()